#ifndef MESSAGE_QUEUE
#define MESSAGE_QUEUE

#include <iostream>
#include <queue>
#include <mutex>
#include <condition_variable>

template <typename T>
class MessageQueue{
public:
    void push(T &message)
    {
        std::unique_lock<std::mutex> lock(mutex_);
        queue_.push(std::move(message));
        lock.unlock();
        condition_.notify_one();
    }

    T pop()
    {
        std::unique_lock<std::mutex> lock(mutex_);
        condition_.wait(lock, [this] { return !queue_.empty(); });
        T message = std::move(queue_.front());
        queue_.pop();
        return message;
    }

    bool empty () const
    {
        std::unique_lock<std::mutex> lock(mutex_);
        return queue_.empty();
    }

private:
    std::queue<T> queue_;
    mutable std::mutex mutex_;
    std::condition_variable condition_;    
};

#endif